module axi_jtag_testbench
	   #
	   (
		   parameter integer C_M_AXI_ADDR_WIDTH = 10,
		   parameter integer C_M_AXI_DATA_WIDTH = 32,

		   parameter integer C_S_AXI_ADDR_WIDTH = 10,
		   parameter integer C_S_AXI_DATA_WIDTH = 32,
		   parameter integer C_TCK_CLOCK_RATIO = 8

	   )
	   (

	   );

reg WENABLE;
wire WBUSY;
wire WERR;

reg RENABLE;
wire RBUSY;
wire RERR;

reg [(C_M_AXI_ADDR_WIDTH - 1): 0] REG_WADDR;
reg [(C_M_AXI_ADDR_WIDTH - 1): 0] REG_RADDR;
reg [1: 0] REG_WDW;
reg [1: 0] REG_RDW;
reg [(C_M_AXI_DATA_WIDTH - 1): 0] REG_WVAL;
wire [(C_M_AXI_DATA_WIDTH - 1): 0] REG_RVAL;

wire axi_lite_aclk;
wire axi_lite_aresetn;
wire axi_lite_awvalid;
wire axi_lite_awready;
wire [(C_M_AXI_ADDR_WIDTH - 1) : 0] axi_lite_awaddr;
wire [2 : 0] axi_lite_awprot;
wire axi_lite_wvalid;
wire axi_lite_wready;
wire [C_M_AXI_DATA_WIDTH - 1 : 0] axi_lite_wdata;
wire [(C_M_AXI_DATA_WIDTH / 8 - 1) : 0] axi_lite_wstrb;
wire axi_lite_bvalid;
wire axi_lite_bready;
wire [1 : 0] axi_lite_bresp;
wire axi_lite_arvalid;
wire axi_lite_arready;
wire [(C_M_AXI_ADDR_WIDTH - 1) : 0] axi_lite_araddr;
wire [2 : 0] axi_lite_arprot;
wire axi_lite_rvalid;
wire axi_lite_rready;
wire [C_M_AXI_DATA_WIDTH - 1 : 0] axi_lite_rdata;
wire [1 : 0] axi_lite_rresp;

wire TCK;
wire TMS;
wire TDI;

template_m_axi_lite
	#
	(
		.C_AXI_ADDR_WIDTH(C_M_AXI_ADDR_WIDTH),
		.C_AXI_DATA_WIDTH(C_M_AXI_DATA_WIDTH)
	)
	template_m_axi_lite_inst
	(
		.WENABLE(WENABLE),
		.WBUSY(WBUSY),
		.WERR(WERR),
		.RENABLE(RENABLE),
		.RBUSY(RBUSY),
		.RERR(RERR),
		.REG_WADDR(REG_WADDR),
		.REG_RADDR(REG_RADDR),
		.REG_WDW(REG_WDW),
		.REG_RDW(REG_RDW),
		.REG_WVAL(REG_WVAL),
		.REG_RVAL(REG_RVAL),
		.m_axi_lite_aclk(axi_lite_aclk),
		.m_axi_lite_aresetn(axi_lite_aresetn),
		.m_axi_lite_awvalid(axi_lite_awvalid),
		.m_axi_lite_awready(axi_lite_awready),
		.m_axi_lite_awaddr(axi_lite_awaddr),
		.m_axi_lite_awprot(axi_lite_awprot),
		.m_axi_lite_wvalid(axi_lite_wvalid),
		.m_axi_lite_wready(axi_lite_wready),
		.m_axi_lite_wdata(axi_lite_wdata),
		.m_axi_lite_wstrb(axi_lite_wstrb),
		.m_axi_lite_bvalid(axi_lite_bvalid),
		.m_axi_lite_bready(axi_lite_bready),
		.m_axi_lite_bresp(axi_lite_bresp),
		.m_axi_lite_arvalid(axi_lite_arvalid),
		.m_axi_lite_arready(axi_lite_arready),
		.m_axi_lite_araddr(axi_lite_araddr),
		.m_axi_lite_arprot(axi_lite_arprot),
		.m_axi_lite_rvalid(axi_lite_rvalid),
		.m_axi_lite_rready(axi_lite_rready),
		.m_axi_lite_rdata(axi_lite_rdata),
		.m_axi_lite_rresp(axi_lite_rresp)
	);

axi_jtag_v1_0
	#
	(
		.C_S_AXI_DATA_WIDTH(C_S_AXI_DATA_WIDTH),
		.C_S_AXI_ADDR_WIDTH(C_S_AXI_ADDR_WIDTH),
		.C_TCK_CLOCK_RATIO(C_TCK_CLOCK_RATIO)
	)
	axi_jtag_instance
	(
		.s_axi_aclk(axi_lite_aclk),
		.s_axi_aresetn(axi_lite_aresetn),
		.s_axi_awaddr(axi_lite_awaddr),
		.s_axi_awprot(axi_lite_awprot),
		.s_axi_awvalid(axi_lite_awvalid),
		.s_axi_awready(axi_lite_awready),
		.s_axi_wdata(axi_lite_wdata),
		.s_axi_wstrb(axi_lite_wstrb),
		.s_axi_wvalid(axi_lite_wvalid),
		.s_axi_wready(axi_lite_wready),
		.s_axi_bresp(axi_lite_bresp),
		.s_axi_bvalid(axi_lite_bvalid),
		.s_axi_bready(axi_lite_bready),
		.s_axi_araddr(axi_lite_araddr),
		.s_axi_arprot(axi_lite_arprot),
		.s_axi_arvalid(axi_lite_arvalid),
		.s_axi_arready(axi_lite_arready),
		.s_axi_rdata(axi_lite_rdata),
		.s_axi_rresp(axi_lite_rresp),
		.s_axi_rvalid(axi_lite_rvalid),
		.s_axi_rready(axi_lite_rready),
		.TCK(TCK),
		.TMS(TMS),
		.TDI(TDI),
		.TDO(TDI)
	);

reg global_clk;
reg global_nrst;

always #(5) global_clk = ~global_clk;

assign axi_lite_aclk = global_clk;
assign axi_lite_aresetn = global_nrst;

initial
begin
	global_clk <= 0;
	global_nrst <= 0;

	#50;
	global_nrst <= 1;
end

`define TEST_TIMES 4

integer i;

initial
begin
	WENABLE <= 0;
	RENABLE <= 0;

	REG_WADDR <= 0;
	REG_RADDR <= 0;
	REG_WDW <= 2;
	REG_RDW <= 2;
	REG_WVAL <= 0;

	#100;

	for (i = 0;i < `TEST_TIMES;i = i + 1)
	begin
		//write to LENGTH
		REG_WADDR <= 'h00;
		REG_WDW <= 2;
		REG_WVAL <= 'd32;
		WENABLE <= 1;
		@(~WBUSY);
		@(WBUSY);
		WENABLE <= 0;
		#20;

		//write to TMS_VECTOR
		REG_WADDR <= 'h04;
		REG_WDW <= 2;
		REG_WVAL <= i;
		WENABLE <= 1;
		@(~WBUSY);
		@(WBUSY);
		WENABLE <= 0;
		#20;

		//write to TDI_VECTOR
		REG_WADDR <= 'h08;
		REG_WDW <= 2;
		REG_WVAL <= 'h11111111 + i;
		WENABLE <= 1;
		@(~WBUSY);
		@(WBUSY);
		WENABLE <= 0;
		#20;

		//write to CTRL
		REG_WADDR <= 'h10;
		REG_WDW <= 2;
		REG_WVAL <= 1;
		WENABLE <= 1;
		@(~WBUSY);
		@(WBUSY);
		WENABLE <= 0;
		#20;

		//read to CTRL
		REG_RADDR <= 'h10;
		REG_RDW <= 2;
		RENABLE <= 1;
		@(~RBUSY);
		@(RBUSY);
		RENABLE <= 0;
		#20;
		
		while(REG_RVAL[0])
		begin
			//read to CTRL
			REG_RADDR <= 'h10;
			REG_RDW <= 2;
			RENABLE <= 1;
			@(~RBUSY);
			@(RBUSY);
			RENABLE <= 0;
			#20;
		end

		//write to CTRL
		REG_RADDR <= 'h0C;
		REG_RDW <= 2;
		RENABLE <= 1;
		@(~RBUSY);
		@(RBUSY);
		RENABLE <= 0;
		#20;

	end


end


endmodule